Skip to content

Add E2E integration test for Gradle plugin#160

Merged
kirich1409 merged 1 commit intomainfrom
test/gradle-plugin-e2e
Apr 29, 2026
Merged

Add E2E integration test for Gradle plugin#160
kirich1409 merged 1 commit intomainfrom
test/gradle-plugin-e2e

Conversation

@kirich1409
Copy link
Copy Markdown
Contributor

Summary

  • Add FeaturedPluginIntegrationTest using Gradle TestKit with a minimal Android app fixture
  • Test verifies generateProguardRules produces correct -assumevalues rules for boolean local flags
  • Test verifies assembleRelease auto-wires the generated ProGuard file via the Variant API
  • Add testPluginClasspath configuration to inject AGP into the TestKit subprocess classpath
  • Add fixture project at src/test/fixtures/android-project/ with minimal Android setup

Tests are skipped when ANDROID_HOME/ANDROID_SDK_ROOT is not set.

Depends on #155

Test plan

  • Run ./gradlew :featured-gradle-plugin:test with ANDROID_HOME set
  • Verify tests pass on CI (Android SDK is available)
  • Verify tests are gracefully skipped when no Android SDK is present

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings April 10, 2026 11:59
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Add E2E integration test for Gradle plugin with Android fixture

🧪 Tests

Grey Divider

Walkthroughs

Description
• Add end-to-end integration test for Gradle plugin using TestKit
• Test verifies ProGuard rules generation with correct -assumevalues blocks
• Test verifies assembleRelease auto-wires generated ProGuard file via AGP Variant API
• Add minimal Android application fixture for integration testing
• Configure testPluginClasspath to inject AGP into TestKit subprocess
Diagram
flowchart LR
  A["Test Configuration"] -->|injects AGP| B["testPluginClasspath"]
  B -->|appended to| C["pluginUnderTestMetadata"]
  C -->|loaded in| D["GradleRunner TestKit"]
  D -->|executes| E["Android Fixture Project"]
  E -->|verifies| F["ProGuard Rules Generation"]
  E -->|verifies| G["assembleRelease Integration"]
Loading

Grey Divider

File Changes

1. featured-gradle-plugin/build.gradle.kts ⚙️ Configuration changes +17/-0

Configure AGP injection for TestKit subprocess

• Create testPluginClasspath configuration to resolve AGP dependency
• Configure pluginUnderTestMetadata task to include testPluginClasspath jars
• Add AGP 9.1.0 as testPluginClasspath dependency for TestKit subprocess injection
• Add comments explaining why AGP must be injected separately from runtimeClasspath

featured-gradle-plugin/build.gradle.kts


2. featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts 🧪 Tests +29/-0

Minimal Android application fixture for testing

• Apply Android application plugin and Featured plugin
• Configure Android namespace, SDK versions (compileSdk 36, minSdk 24, targetSdk 36)
• Enable minification for release build with default ProGuard file
• Declare dark_mode boolean local flag in Featured plugin configuration

featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts


3. featured-gradle-plugin/src/test/fixtures/android-project/settings.gradle.kts ⚙️ Configuration changes +31/-0

Fixture project repository and plugin configuration

• Configure pluginManagement repositories for AGP and plugin resolution
• Configure dependencyResolutionManagement with Google Maven and Maven Central
• Set root project name to android-project
• Include repository filters for Android, Google, and AndroidX artifacts

featured-gradle-plugin/src/test/fixtures/android-project/settings.gradle.kts


View more (2)
4. featured-gradle-plugin/src/test/fixtures/android-project/src/main/AndroidManifest.xml 🧪 Tests +1/-0

Minimal Android manifest for fixture

• Create minimal Android manifest file required by AGP compilation

featured-gradle-plugin/src/test/fixtures/android-project/src/main/AndroidManifest.xml


5. featured-gradle-plugin/src/test/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPluginIntegrationTest.kt 🧪 Tests +198/-0

End-to-end integration test for Gradle plugin

• Create FeaturedPluginIntegrationTest class using Gradle TestKit for end-to-end testing
• Test generateProguardRules task produces correct -assumevalues rules for boolean flags
• Test assembleRelease auto-wires generated ProGuard file and completes successfully
• Skip tests when ANDROID_HOME or ANDROID_SDK_ROOT environment variables are not set
• Implement fixture copying, SDK directory resolution, and GradleRunner configuration
• Verify ProGuard output contains expected extension class FQN and method signatures

featured-gradle-plugin/src/test/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPluginIntegrationTest.kt


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Apr 10, 2026

Code Review by Qodo

🐞 Bugs (3)   📘 Rule violations (2)   📎 Requirement gaps (0)   🎨 UX Issues (0)
🐞\ ≡ Correctness (1) ☼ Reliability (2)
📘\ ⚙ Maintainability (2)

Grey Divider


Action required

1. Hardcoded AGP in testPluginClasspath 📘
Description
The build script adds an AGP dependency with a literal version string (9.1.0) instead of sourcing
the version from the Gradle version catalog. This can lead to version drift and violates the
requirement to declare dependency versions centrally.
Code

featured-gradle-plugin/build.gradle.kts[74]

+    testPluginClasspath("com.android.tools.build:gradle:9.1.0")
Evidence
The compliance rule requires dependency versions to be referenced via the version catalog rather
than hardcoded. The added dependency declaration uses a literal version string in
testPluginClasspath("com.android.tools.build:gradle:9.1.0").

Rule 162994: Declare all dependency versions in Gradle version catalog
featured-gradle-plugin/build.gradle.kts[74-74]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A dependency version is hardcoded as `9.1.0` in `featured-gradle-plugin/build.gradle.kts`, violating the requirement to declare dependency versions in the Gradle version catalog.

## Issue Context
`gradle/libs.versions.toml` already defines `agp = "9.1.0"`, but the build script still hardcodes the version in the dependency coordinate.

## Fix Focus Areas
- featured-gradle-plugin/build.gradle.kts[74-74]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Fixture uses plugin version literal 📘
Description
The fixture project applies com.android.application with a hardcoded version (9.1.0) in `plugins
{}`. This violates the requirement to avoid literal version strings in Gradle build scripts.
Code

featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts[2]

+    id("com.android.application") version "9.1.0"
Evidence
The compliance rule prohibits literal version strings in build scripts. The added fixture build
script contains id("com.android.application") version "9.1.0", which is a hardcoded version.

Rule 162994: Declare all dependency versions in Gradle version catalog
featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts[2-2]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The TestKit fixture `build.gradle.kts` applies `com.android.application` with a hardcoded plugin version string (`9.1.0`).

## Issue Context
This fixture is used for TestKit E2E tests and should not hardcode versions in the build script. If AGP is injected via the TestKit classpath, the fixture can typically apply the plugin without specifying a version.

## Fix Focus Areas
- featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts[1-4]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. assembleRelease not wired 🐞
Description
FeaturedPluginIntegrationTest asserts :generateProguardRules runs during assembleRelease, but
the Featured plugin currently only registers the task and does not wire it into AGP variants, and
the fixture does not include the generated .pro file in proguardFiles. This will cause the test
to fail because result.task(":generateProguardRules") will be null or not executed during
assembleRelease.
Code

featured-gradle-plugin/src/test/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPluginIntegrationTest.kt[R79-84]

+        // generateProguardRules must have run as part of the release build.
+        val proguardOutcome = result.task(":generateProguardRules")?.outcome
+        assertTrue(
+            proguardOutcome == TaskOutcome.SUCCESS || proguardOutcome == TaskOutcome.UP_TO_DATE,
+            "Expected :generateProguardRules to participate in assembleRelease, got $proguardOutcome\n${result.output}",
+        )
Evidence
The test requires generateProguardRules to participate in assembleRelease. However,
FeaturedPlugin only registers generateProguardRules and does not configure any Android/variant
hooks or dependencies to connect it to assembleRelease. The fixture’s release build type also
only specifies the default ProGuard file and never references
build/featured/proguard-featured.pro, so AGP has no reason to run the generation task as part of
minification.

featured-gradle-plugin/src/test/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPluginIntegrationTest.kt[72-97]
featured-gradle-plugin/src/main/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPlugin.kt[37-58]
featured-gradle-plugin/src/main/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPlugin.kt[99-111]
featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts[15-22]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new E2E test expects `assembleRelease` to trigger `generateProguardRules`, but the plugin/fixture currently do not wire the generated ProGuard file into AGP’s release variant. This makes the test fail because `:generateProguardRules` will not be in the task graph for `assembleRelease`.

## Issue Context
- The plugin registers `generateProguardRules` and writes `build/featured/proguard-featured.pro`.
- The fixture’s `release` build type does not reference this file.
- There is no Android Components/Variant API integration in the plugin to add this file automatically.

## Fix Focus Areas
- featured-gradle-plugin/src/main/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPlugin.kt[37-58]
- featured-gradle-plugin/src/main/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPlugin.kt[99-111]
- featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts[15-22]
- featured-gradle-plugin/src/test/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPluginIntegrationTest.kt[72-97]

## What to change
1. Implement actual AGP integration in the Featured plugin so that for release variants it:
  - adds `build/featured/proguard-featured.pro` to the variant’s ProGuard/R8 configuration, and
  - ensures the relevant R8/minify task depends on `generateProguardRules` (or otherwise consumes its output via the Variant API).
2. Keep the fixture minimal (it should not manually add the file if the plugin is supposed to auto-wire it).
3. If auto-wiring is not intended yet, adjust the test and fixture accordingly (but then remove the “auto-wires” claim and the `assembleRelease` participation assertion).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. AGP double-resolution risk 🐞
Description
AGP is appended to the TestKit plugin classpath via pluginUnderTestMetadata, but the fixture still
applies com.android.application with an explicit version. This can cause Gradle plugin resolution
to fail because the plugin is already on the classpath while also being requested with a version.
Code

featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts[R1-4]

+plugins {
+    id("com.android.application") version "9.1.0"
+    id("dev.androidbroadcast.featured")
+}
Evidence
The plugin module explicitly injects com.android.tools.build:gradle:9.1.0 into
pluginUnderTestMetadata, which is the classpath used by GradleRunner.withPluginClasspath() for
the subprocess. The fixture then requests com.android.application with version "9.1.0", which is
incompatible with the ‘plugin already on classpath’ application mode TestKit uses.

featured-gradle-plugin/build.gradle.kts[57-75]
featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts[1-4]
featured-gradle-plugin/src/test/fixtures/android-project/settings.gradle.kts[1-15]
Best Practice: Gradle plugins DSL semantics

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
AGP is injected into the TestKit subprocess classpath via `pluginUnderTestMetadata`, but the fixture still requests the Android plugin with an explicit version. This can break Gradle’s plugin resolution (plugin already on classpath + versioned request).

## Issue Context
The goal of `testPluginClasspath` is to make AGP available in the TestKit subprocess without relying on external plugin resolution.

## Fix Focus Areas
- featured-gradle-plugin/build.gradle.kts[57-75]
- featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts[1-4]
- featured-gradle-plugin/src/test/fixtures/android-project/settings.gradle.kts[1-15]

## What to change
- Prefer one mechanism:
 1) **Injected-classpath approach (recommended here):**
    - Change fixture to `plugins { id("com.android.application"); id("dev.androidbroadcast.featured") }` (no version for AGP).
    - Optionally simplify/remove `pluginManagement.repositories` if it’s no longer needed.
 OR
 2) **Repository resolution approach:**
    - Remove AGP from `testPluginClasspath` injection and keep the fixture’s versioned plugin request.

Ensure the chosen approach is consistent with the comments in the fixture/settings files.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

5. Windows sdk.dir may break 🐞
Description
The integration test writes local.properties using sdkDir.absolutePath, which contains
backslashes on Windows and can be mis-parsed by Java .properties escaping rules. This can make the
test fail to locate the SDK on Windows environments.
Code

featured-gradle-plugin/src/test/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPluginIntegrationTest.kt[R45-46]

+        // Write local.properties with sdk.dir so AGP can locate the Android SDK.
+        projectDir.resolve("local.properties").writeText("sdk.dir=${sdkDir!!.absolutePath}\n")
Evidence
local.properties is a Java properties file; writing a raw Windows path (e.g., C:\Android\Sdk)
without escaping backslashes can corrupt the parsed value. The test currently writes the path
verbatim.

featured-gradle-plugin/src/test/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPluginIntegrationTest.kt[34-47]
Best Practice: Java Properties file format

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test writes `sdk.dir` into `local.properties` without normalizing/escaping the path, which can break on Windows.

## Issue Context
`local.properties` is parsed as Java properties. Windows paths contain `\` which are escape characters in this format.

## Fix Focus Areas
- featured-gradle-plugin/src/test/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPluginIntegrationTest.kt[34-47]

## What to change
- Write `sdk.dir` using a properties-safe path, e.g.:
 - `sdkDir.absolutePath.replace('\\', '/')` (forward slashes), or
 - escape backslashes: `sdkDir.absolutePath.replace("\\", "\\\\")`.
- Keep the newline terminator.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Gradle TestKit-based end-to-end integration test for :featured-gradle-plugin using a minimal Android app fixture, aiming to validate ProGuard rule generation and (intended) release-variant wiring.

Changes:

  • Introduce FeaturedPluginIntegrationTest that runs generateProguardRules and assembleRelease against a fixture Android app.
  • Add an Android fixture project under src/test/fixtures/android-project/.
  • Extend pluginUnderTestMetadata classpath via a new testPluginClasspath configuration (to inject AGP into the TestKit subprocess).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
featured-gradle-plugin/src/test/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPluginIntegrationTest.kt New TestKit E2E test verifying ProGuard output and (intended) wiring into assembleRelease.
featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts Minimal Android app applying AGP + Featured plugin and declaring a boolean local flag.
featured-gradle-plugin/src/test/fixtures/android-project/settings.gradle.kts Fixture repositories/pluginManagement setup for TestKit build.
featured-gradle-plugin/src/test/fixtures/android-project/src/main/AndroidManifest.xml Minimal manifest for the fixture app.
featured-gradle-plugin/build.gradle.kts Adds testPluginClasspath and appends it to pluginUnderTestMetadata for TestKit.

Comment on lines +73 to +83
fun `assembleRelease wires proguard rules and completes successfully`() {
val result =
gradleRunner(projectDir)
.withArguments("assembleRelease", "--stacktrace")
.build()

// generateProguardRules must have run as part of the release build.
val proguardOutcome = result.task(":generateProguardRules")?.outcome
assertTrue(
proguardOutcome == TaskOutcome.SUCCESS || proguardOutcome == TaskOutcome.UP_TO_DATE,
"Expected :generateProguardRules to participate in assembleRelease, got $proguardOutcome\n${result.output}",
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assembleRelease test currently expects :generateProguardRules to run as part of the Android release build, but FeaturedPlugin only registers the generateProguardRules task and does not wire it into any Android variant/task graph (no Variant API wiring in FeaturedPlugin). As-is, assembleRelease in the fixture won't invoke generateProguardRules, so this test should fail unless the wiring code is included in this PR branch. Either include the wiring change (from the dependent PR) in this branch or change the fixture/build to explicitly add the generated .pro file to proguardFiles(...) and adjust the assertion accordingly.

Suggested change
fun `assembleRelease wires proguard rules and completes successfully`() {
val result =
gradleRunner(projectDir)
.withArguments("assembleRelease", "--stacktrace")
.build()
// generateProguardRules must have run as part of the release build.
val proguardOutcome = result.task(":generateProguardRules")?.outcome
assertTrue(
proguardOutcome == TaskOutcome.SUCCESS || proguardOutcome == TaskOutcome.UP_TO_DATE,
"Expected :generateProguardRules to participate in assembleRelease, got $proguardOutcome\n${result.output}",
fun `generateProguardRules and assembleRelease complete successfully`() {
val result =
gradleRunner(projectDir)
.withArguments("generateProguardRules", "assembleRelease", "--stacktrace")
.build()
// Explicitly invoke generateProguardRules before assembleRelease for the current plugin behavior.
val proguardOutcome = result.task(":generateProguardRules")?.outcome
assertTrue(
proguardOutcome == TaskOutcome.SUCCESS || proguardOutcome == TaskOutcome.UP_TO_DATE,
"Expected :generateProguardRules to succeed before assembleRelease, got $proguardOutcome\n${result.output}",

Copilot uses AI. Check for mistakes.
Comment on lines +156 to +169
/**
* Resolves the fixture directory. The plugin module's project directory is either
* injected as the `user.dir` system property by Gradle's test task, or derived
* relative to this class file's location.
*/
private fun fixtureDir(): File {
// Gradle's test task sets user.dir to the module project directory.
val moduleDir = File(System.getProperty("user.dir"))
val candidate = moduleDir.resolve("src/test/fixtures/android-project")
require(candidate.isDirectory) {
"Fixture directory not found at ${candidate.absolutePath}. " +
"Expected it relative to module project dir: ${moduleDir.absolutePath}"
}
return candidate
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The KDoc for fixtureDir() says the module directory is either provided via user.dir or derived relative to this class file's location, but the implementation only uses System.getProperty("user.dir") and has no fallback. Either implement the described fallback (e.g., resolve via a classpath resource) or update the KDoc to match the actual behavior to avoid confusion and brittle test setup.

Copilot uses AI. Check for mistakes.
Comment on lines +175 to +179
* AGP is declared as `compileOnly` in this module — the applying build provides it at runtime.
* In the TestKit subprocess, AGP is loaded by the build's own classloader when `com.android.application`
* is applied from the fixture's `plugins {}` block (resolved from Google Maven). The Featured plugin
* code that references [com.android.build.api.variant.AndroidComponentsExtension] is loaded in the
* same classloader context, so no extra classpath injection is needed.
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The gradleRunner() KDoc claims “no extra classpath injection is needed”, but this PR adds testPluginClasspath to inject AGP into pluginUnderTestMetadata. This comment is now misleading (and the classloader explanation is likely incorrect in TestKit). Please update the KDoc to reflect the actual mechanism being used so future changes don’t accidentally remove required classpath setup.

Suggested change
* AGP is declared as `compileOnly` in this module — the applying build provides it at runtime.
* In the TestKit subprocess, AGP is loaded by the build's own classloader when `com.android.application`
* is applied from the fixture's `plugins {}` block (resolved from Google Maven). The Featured plugin
* code that references [com.android.build.api.variant.AndroidComponentsExtension] is loaded in the
* same classloader context, so no extra classpath injection is needed.
* The runner uses [GradleRunner.withPluginClasspath] so TestKit loads the plugin-under-test from
* the generated `pluginUnderTestMetadata` classpath.
*
* This test setup also relies on additional classpath wiring for that metadata so AGP is available
* to the plugin under test, even though AGP is declared as `compileOnly` in this module. Keep that
* wiring in place when changing the test configuration; removing it can break access to
* [com.android.build.api.variant.AndroidComponentsExtension] during the TestKit build.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,29 @@
plugins {
id("com.android.application") version "9.1.0"
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fixture applies com.android.application with an explicit version. With TestKit, this typically resolves/loads AGP via plugin resolution rather than from the injected withPluginClasspath() classpath, while this PR also injects com.android.tools.build:gradle into the plugin-under-test classpath. That combination can create classloader/type-identity issues (e.g., AndroidComponentsExtension loaded twice) and make Variant API lookups/casts fail. Prefer applying com.android.application without a version here so it uses the injected classpath, keeping AGP types consistent.

Suggested change
id("com.android.application") version "9.1.0"
id("com.android.application")

Copilot uses AI. Check for mistakes.
dependencies {
// Inject AGP into the TestKit subprocess via pluginUnderTestMetadata so that the Featured
// plugin can access AndroidComponentsExtension when wireProguardToVariants() is called.
testPluginClasspath("com.android.tools.build:gradle:9.1.0")
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AGP version is hard-coded as 9.1.0 in the new testPluginClasspath dependency. Since the repo already tracks the AGP version in the version catalog (libs.versions.agp), this should be sourced from there to avoid accidental drift (tests may break if the plugin’s compileOnly AGP version changes but this stays pinned).

Suggested change
testPluginClasspath("com.android.tools.build:gradle:9.1.0")
testPluginClasspath("com.android.tools.build:gradle:${libs.versions.agp.get()}")

Copilot uses AI. Check for mistakes.
dependencies {
// Inject AGP into the TestKit subprocess via pluginUnderTestMetadata so that the Featured
// plugin can access AndroidComponentsExtension when wireProguardToVariants() is called.
testPluginClasspath("com.android.tools.build:gradle:9.1.0")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Hardcoded agp in testpluginclasspath 📘 Rule violation ⚙ Maintainability

The build script adds an AGP dependency with a literal version string (9.1.0) instead of sourcing
the version from the Gradle version catalog. This can lead to version drift and violates the
requirement to declare dependency versions centrally.
Agent Prompt
## Issue description
A dependency version is hardcoded as `9.1.0` in `featured-gradle-plugin/build.gradle.kts`, violating the requirement to declare dependency versions in the Gradle version catalog.

## Issue Context
`gradle/libs.versions.toml` already defines `agp = "9.1.0"`, but the build script still hardcodes the version in the dependency coordinate.

## Fix Focus Areas
- featured-gradle-plugin/build.gradle.kts[74-74]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@@ -0,0 +1,29 @@
plugins {
id("com.android.application") version "9.1.0"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Fixture uses plugin version literal 📘 Rule violation ⚙ Maintainability

The fixture project applies com.android.application with a hardcoded version (9.1.0) in `plugins
{}`. This violates the requirement to avoid literal version strings in Gradle build scripts.
Agent Prompt
## Issue description
The TestKit fixture `build.gradle.kts` applies `com.android.application` with a hardcoded plugin version string (`9.1.0`).

## Issue Context
This fixture is used for TestKit E2E tests and should not hardcode versions in the build script. If AGP is injected via the TestKit classpath, the fixture can typically apply the plugin without specifying a version.

## Fix Focus Areas
- featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts[1-4]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +79 to +84
// generateProguardRules must have run as part of the release build.
val proguardOutcome = result.task(":generateProguardRules")?.outcome
assertTrue(
proguardOutcome == TaskOutcome.SUCCESS || proguardOutcome == TaskOutcome.UP_TO_DATE,
"Expected :generateProguardRules to participate in assembleRelease, got $proguardOutcome\n${result.output}",
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Assemblerelease not wired 🐞 Bug ≡ Correctness

FeaturedPluginIntegrationTest asserts :generateProguardRules runs during assembleRelease, but
the Featured plugin currently only registers the task and does not wire it into AGP variants, and
the fixture does not include the generated .pro file in proguardFiles. This will cause the test
to fail because result.task(":generateProguardRules") will be null or not executed during
assembleRelease.
Agent Prompt
## Issue description
The new E2E test expects `assembleRelease` to trigger `generateProguardRules`, but the plugin/fixture currently do not wire the generated ProGuard file into AGP’s release variant. This makes the test fail because `:generateProguardRules` will not be in the task graph for `assembleRelease`.

## Issue Context
- The plugin registers `generateProguardRules` and writes `build/featured/proguard-featured.pro`.
- The fixture’s `release` build type does not reference this file.
- There is no Android Components/Variant API integration in the plugin to add this file automatically.

## Fix Focus Areas
- featured-gradle-plugin/src/main/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPlugin.kt[37-58]
- featured-gradle-plugin/src/main/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPlugin.kt[99-111]
- featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts[15-22]
- featured-gradle-plugin/src/test/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPluginIntegrationTest.kt[72-97]

## What to change
1. Implement actual AGP integration in the Featured plugin so that for release variants it:
   - adds `build/featured/proguard-featured.pro` to the variant’s ProGuard/R8 configuration, and
   - ensures the relevant R8/minify task depends on `generateProguardRules` (or otherwise consumes its output via the Variant API).
2. Keep the fixture minimal (it should not manually add the file if the plugin is supposed to auto-wire it).
3. If auto-wiring is not intended yet, adjust the test and fixture accordingly (but then remove the “auto-wires” claim and the `assembleRelease` participation assertion).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +1 to +4
plugins {
id("com.android.application") version "9.1.0"
id("dev.androidbroadcast.featured")
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Agp double-resolution risk 🐞 Bug ☼ Reliability

AGP is appended to the TestKit plugin classpath via pluginUnderTestMetadata, but the fixture still
applies com.android.application with an explicit version. This can cause Gradle plugin resolution
to fail because the plugin is already on the classpath while also being requested with a version.
Agent Prompt
## Issue description
AGP is injected into the TestKit subprocess classpath via `pluginUnderTestMetadata`, but the fixture still requests the Android plugin with an explicit version. This can break Gradle’s plugin resolution (plugin already on classpath + versioned request).

## Issue Context
The goal of `testPluginClasspath` is to make AGP available in the TestKit subprocess without relying on external plugin resolution.

## Fix Focus Areas
- featured-gradle-plugin/build.gradle.kts[57-75]
- featured-gradle-plugin/src/test/fixtures/android-project/build.gradle.kts[1-4]
- featured-gradle-plugin/src/test/fixtures/android-project/settings.gradle.kts[1-15]

## What to change
- Prefer one mechanism:
  1) **Injected-classpath approach (recommended here):**
     - Change fixture to `plugins { id("com.android.application"); id("dev.androidbroadcast.featured") }` (no version for AGP).
     - Optionally simplify/remove `pluginManagement.repositories` if it’s no longer needed.
  OR
  2) **Repository resolution approach:**
     - Remove AGP from `testPluginClasspath` injection and keep the fixture’s versioned plugin request.

Ensure the chosen approach is consistent with the comments in the fixture/settings files.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@kirich1409 kirich1409 added this to the v1.0.0 milestone Apr 29, 2026
Add FeaturedPluginIntegrationTest that uses Gradle TestKit with a minimal
Android application fixture to verify:
- generateProguardRules produces correct -assumevalues rules
- assembleRelease auto-wires the generated proguard file via Variant API

Tests are skipped when ANDROID_HOME is not set. The testPluginClasspath
configuration injects AGP into the TestKit subprocess classpath.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kirich1409 kirich1409 force-pushed the test/gradle-plugin-e2e branch from 1fbb57d to 78397c5 Compare April 29, 2026 12:58
@kirich1409 kirich1409 merged commit 2651f7e into main Apr 29, 2026
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants